﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using GC_FFW.BusinessEntities.Soccerfame.Xml;
using GC_FFW.Common.Abstractions.Interfaces.Helpers;
using GC_FFW.SoccerfameParser.Abstractions.Interfaces.Repositories;

namespace GC_FFW.SoccerfameParser.Repositories
{
	public class NamesRepository : INamesRepository
	{
		#region Variables

		private readonly IXmlSerializerService _xmlSerializerService;
		private readonly string _filePath;
		private readonly Names _data;

		#endregion

		#region Constructors

		public NamesRepository(IXmlSerializerService xmlSerializerService, string filePath)
		{
			if (xmlSerializerService == null)
				throw new ArgumentNullException(string.Format("xmlSerializerService"));
			_xmlSerializerService = xmlSerializerService;

			if (string.IsNullOrWhiteSpace(filePath) || !File.Exists(filePath))
				throw new FileNotFoundException();
			_filePath = filePath;

			_data = _xmlSerializerService.Deserialize<Names>(_filePath) ?? new Names();
			if (_data.Items == null)
				_data.Items = new List<Name>();
		}

		#endregion

		#region INamesService Members

		public Names Get()
		{
			return _data.Clone() as Names;
		}

		public Name GetByName(string data, bool isValidName)
		{
			var result = FindByName(data, isValidName);
			return result != null
				? result.Clone() as Name
				: null;
		}

		public void Save(string validName, string invalidName)
		{
			Update(validName, invalidName);

			_xmlSerializerService.SerializeToXML(_data, _filePath);
		}

		public void Save(IDictionary<string, string> data)
		{
			if (data == null || !data.Any()) return;

			foreach (var item in data)
			{
				Update(item.Value, item.Key);
			}

			_xmlSerializerService.SerializeToXML(_data, _filePath);
		}

		#endregion

		#region Internal Implementation

		private Name FindByName(string data, bool isValidName)
		{
			return _data.Items.FirstOrDefault(i => isValidName ? i.ValidValue == data : i.InvalidValue == data);
		}

		private void Update(string validName, string invalidName)
		{
			if (string.IsNullOrWhiteSpace(validName) || string.IsNullOrWhiteSpace(invalidName)
				|| _data == null)
				return;

			if (_data.Items == null)
				_data.Items = new List<Name>();

			var existingItem = FindByName(invalidName, false);
			if (existingItem != null)
				existingItem.ValidValue = validName;
			else
				_data.Items.Add(new Name { InvalidValue = invalidName, ValidValue = validName });
		}

		#endregion
	}
}
